﻿using System;
using CoreTypes;
using System.Linq;
using System.Custom;
using System.Drawing;
using System.Custom.Window;
using System.Globalization;
using System.Windows.Forms;
using System.ComponentModel;
using MainModule.Properties;
using System.Collections.Generic;

namespace MainModule
{
   public partial class SearchWindow : Window
   {
      #region Window Data

      InternetCommunicator FCommunicator;

      List<User> FSearchResults = new List<User>();

      Color FPanelSearchBlueColor = Color.FromArgb(100, 135, 220); // Color.FromArgb(140, 170, 230);
      Color FSearchParamsBodyBlueColor = Color.FromArgb(214, 223, 247);

      Color FPanelSearchOliveColor = Color.FromArgb(175, 185, 136); // Color.FromArgb(211, 217, 188);
      Color FSearchParamsBodyOliveColor = Color.FromArgb(238, 246, 228);

      Color FPanelSearchSilverColor = Color.FromArgb(166, 164, 186); // Color.FromArgb(224, 224, 223);
      Color FSearchParamsBodySilverColor = Color.FromArgb(240, 240, 255);

      Color FPanelSearchStandardColor = Color.FromArgb(58, 110, 165);

      int FToolStripMainControlsWidth;

      #endregion

      public SearchWindow(bool simple)
      {
         InitializeComponent();

         FCommunicator = InternetCommunicator.Self;

         window_SizeChanged(this, null);

         panelName.Tag = panelName.Height;
         panelLanguage.Tag = panelLanguage.Height;
         panelGender.Tag = panelGender.Height;
         panelAge.Tag = panelAge.Height;
         panelLocation.Tag = panelLocation.Height;
         panelWork.Tag = panelWork.Height;
         panelPresence.Tag = panelPresence.Height;

         ColorTheme = FCommunicator.ColorTheme;
         RenderMode = FCommunicator.RenderMode;
         imageListResultsView.Images.Add(ResourceWrapper.GetImage("StatusOfflineTray"));

         FCommunicator.SeekUsersState += communicator_SeekUsersState;
         FCommunicator.PropertyChanged += communicator_PropertyChanged;
         FCommunicator.CurrentAccountChanged += communicator_CurrentAccountChanged;

         comboBoxGender.Items.AddRange(new object[] { "", Resources.S_Male, Resources.S_Female });

         comboBoxLanguage.Items.Add("");
         comboBoxLanguage.Items.Add(CultureInfo.CurrentUICulture.Parent.DisplayName);
         comboBoxLanguage.Items.AddRange(Cultures.Neutral.Select(c => c.DisplayName).ToArray());

         comboBoxCountry.Items.Add("");
         comboBoxCountry.Items.Add(RegionInfo.CurrentRegion.DisplayName.TrimIgnoreNull());
         comboBoxCountry.Items.AddRange(Cultures.Countries);

         foreach (ToolStripItem item in toolStripMain.Items)
         {
            if (item != textBoxQuickSearch) FToolStripMainControlsWidth += item.Width;
         }
         FToolStripMainControlsWidth += 25;
      }
      protected override void Dispose(bool disposing)
      {
         FCommunicator.SeekUsersState -= communicator_SeekUsersState;
         FCommunicator.PropertyChanged -= communicator_PropertyChanged;
         FCommunicator.CurrentAccountChanged -= communicator_CurrentAccountChanged;
         
         if (disposing && (components != null))
         {
            components.Dispose();
         }
         base.Dispose(disposing);
      }

      public bool SimpleMode
      {
         get
         {
            return !buttonPeopleSearch.Checked;
         }
         set
         {
            buttonPeopleSearch.Checked = !value;
            splitContainer.Panel1Collapsed = value;
            if (!value && CompactMode) CompactMode = false;
            ResetSearch();
         }
      }
      public bool CompactMode
      {
         get
         {
            return Size == MinimumSize;
         }
         set
         {
            Size = value ? MinimumSize : new Size(850, 705);
            CenterToScreen();
         }
      }
      public override ColorTheme ColorTheme
      {
         get
         {
            return base.ColorTheme;
         }
         set
         {
            base.ColorTheme = value;
            Refresh();
         }
      }
      public override ToolStripRenderMode RenderMode
      {
         get
         {
            return base.RenderMode;
         }
         set
         {
            base.RenderMode = value;
            toolStripMain.RenderMode = value;
            statusBar.RenderMode = value;
            //statusBar.Refresh();
         }
      }

      public void Show(bool simple)
      {
         Hide();
         SimpleMode = CompactMode = simple;
         AssignCapabilities();
         Visualize();
         labelCaption.Text = Resources.S_Search_people_at_service_catalog.Replace("<service>", FCommunicator.CurrentAccount.ServiceConfig.ToString());

         if (SimpleMode) textBoxQuickSearch.Focus(); else textBoxName.Focus();
      }
      public override void Translate(CultureInfo culture)
      {
         base.Translate(culture);
         UpdatewWindowView();
      }

      private void ResetSearch()
      {
         ResetResultsView(SimpleMode);

         textBoxQuickSearch.Text = "";
         textBoxName.Text = "";
         textBoxOrganization.Text = "";
         textBoxDepartment.Text = "";
         comboBoxLanguage.SelectedIndex = -1;
         comboBoxCountry.SelectedIndex = -1;
         textBoxCity.Text = "";
         comboBoxAge.SelectedIndex = -1;
         comboBoxGender.SelectedIndex = -1;
         checkBoxOnlineOnly.Checked = false;
      }
      private void AssignCapabilities()
      {
         ResetSearch();

         Account account = FCommunicator.CurrentAccount;

         panelSearch.Enabled = account.ServiceConfig.SupportsFeature(ServiceFeatures.PeopleSearch);
         toolStripMain.Enabled = listViewResults.Enabled = panelSearch.Enabled || account.ServiceConfig.SupportsFeature(ServiceFeatures.FindPerson);

         comboBoxCountry.Enabled = account.ServiceConfig.SupportsSearchBy(ServiceFields.Country);
         textBoxCity.Enabled = account.ServiceConfig.SupportsSearchBy(ServiceFields.City);
         textBoxOrganization.Enabled = account.ServiceConfig.SupportsSearchBy(ServiceFields.Organization);
         textBoxDepartment.Enabled = account.ServiceConfig.SupportsSearchBy(ServiceFields.Department);

         labelSearchComment.Height = account.ServiceConfig.SupportsFeature(ServiceFeatures.SearchByMask) ? 30 : 0;
         panelName.Height = account.ServiceConfig.SupportsSearchBy(ServiceFields.FullName) ? (int)panelName.Tag : 0;
         panelLanguage.Height = account.ServiceConfig.SupportsSearchBy(ServiceFields.Language) ? (int)panelLanguage.Tag : 0;
         panelGender.Height = account.ServiceConfig.SupportsSearchBy(ServiceFields.Gender) ? (int)panelGender.Tag : 0;
         panelAge.Height = account.ServiceConfig.SupportsSearchBy(ServiceFields.Birthday) ? (int)panelAge.Tag : 0;
         panelLocation.Height = account.ServiceConfig.SupportsSearchBy(ServiceFields.Country) ||
                                account.ServiceConfig.SupportsSearchBy(ServiceFields.City) ? (int)panelLocation.Tag : 0;
         panelWork.Height = account.ServiceConfig.SupportsSearchBy(ServiceFields.Organization) ||
                            account.ServiceConfig.SupportsSearchBy(ServiceFields.Department) ? (int)panelWork.Tag : 0;
         panelPresence.Height = account.ServiceConfig.SupportsSearchBy(ServiceFields.NetworkStatus) ? (int)panelPresence.Tag : 0;

         int h = panelName.Height +
                 panelLanguage.Height +
                 panelLocation.Height +
                 panelAge.Height +
                 panelGender.Height +
                 panelPresence.Height +                 
                 panelWork.Height;

         panelSearchParams.MaximumSize = new Size(0, h + labelSearchComment.Height + panelButtonSearch.Height + 75);
         panelSearchParams.Height = panelSearchParams.MaximumSize.Height;
         panelSearchParams.Enabled = h > 0;
         panelSearchParams.Refresh();

         if (panelSearch.Enabled) panelSearch.Enabled = panelSearchParams.Enabled;
         buttonPeopleSearch.Enabled = panelSearchParams.Enabled;
         labelSearchCaption.Text = panelSearch.Enabled ? Resources.S_Search_people_using : Resources.S_People_search_is_unavailable;
         if (!panelSearch.Enabled && toolStripMain.Enabled) SimpleMode = CompactMode = true;
      }
      private string GetMisc(UserInfo info)
      {
         string misc = "";

         if (info.Work.Organization != "") misc += Resources.S_Organization + ": \"" + info.Work.Organization + "\";";
         if (info.Work.Department != "") misc += " " + Resources.S_Department + ": \"" + info.Work.Department + "\";";

         return misc;
      }
      protected override void UpdatewWindowView()
      {
         labelSearchCaption.Text = panelSearch.Enabled ? Resources.S_Search_people_using : Resources.S_People_search_is_unavailable;
      }
      private void ResetResultsView(bool forPerson)
      {
         FSearchResults.Clear();
         listViewResults.Items.Clear();
         listViewResults.Columns.Clear();
         statusBar.Items[0].Text = Resources.S_Ready;

         if (forPerson)
         {
            listViewResults.Columns.AddRange(new ColumnHeader[] {
                                             columnUsername,
                                             columnNickname,
                                             columnName,
                                             columnLanguage,
                                             columnCountry,
                                             columnCity,
                                             columnAge });
         }
         else
         {
            listViewResults.Columns.AddRange(new ColumnHeader[] {
                                             columnUsername,
                                             columnNickname,
                                             columnLanguage,
                                             columnCountry,
                                             columnCity,
                                             columnGender,
                                             columnAge,
                                             columnDescription,
                                             columnMisc});
         }
      }
      private void ShowResults(OperationState state, IEnumerable<User> users)
      {
         foreach (User user in users)
         {
            ListViewItem item = new ListViewItem(user.Login, 0);

            item.Tag = user;

            if (SimpleMode)
            {
               item.SubItems.AddRange(new string[] {
                                                   user.Nickname,
                                                   user.Info.FullName,
                                                   user.Info.Language,
                                                   user.Info.Country,
                                                   user.Info.City,
                                                   user.Info.Age });
            }
            else
            {
               item.SubItems.AddRange(new string[] {
                                                   user.Nickname,
                                                   user.Info.Language,
                                                   user.Info.Country,
                                                   user.Info.City,
                                                   UserInfo.GetGenderAsString(user.Info.Gender, false),
                                                   user.Info.Age,
                                                   user.Info.Description,
                                                   GetMisc(user.Info) });
            }
            listViewResults.Items.Add(item);
         }

         FSearchResults.AddRange(users);

         statusBar.Items[0].Text = FSearchResults.Count + (FSearchResults.Count == 1 ? " user found" : " users found");

         statusBar.Items[0].Text += state == OperationState.Completed ? "." : "...";

         if (state == OperationState.Completed && WindowState == FormWindowState.Minimized)
         {
            FlashWindow(FlashType.Window, 3, null);
         }
      }

      private void panel_Click(object sender, EventArgs e)
      {
         panelSearch.Focus();
      }
      private void buttonGo_Click(object sender, EventArgs e)
      {
         FCommunicator.SeekUsers(textBoxQuickSearch.Text, this);
      }
      private void window_KeyDown(object sender, KeyEventArgs e)
      {
         if (e.KeyCode == Keys.Escape)
         {
            Close();
         }
         else if (e.KeyCode == Keys.Enter)
         {
            if (textBoxQuickSearch.Focused) buttonGo_Click(sender, null);
            else if (listViewResults.Focused) buttonShowInfo_Click(sender, null);
            else buttonSearch_Click(sender, null);
            e.SuppressKeyPress = true;
         }
         else if (e.Control && e.KeyCode == Keys.R)
         {
            listViewResults.Focus();
            if (listViewResults.Items.Count > 0) listViewResults.FocusedItem = listViewResults.Items[0];
         }
      }
      private void window_SizeChanged(object sender, EventArgs e)
      {
         textBoxQuickSearch.Width = toolStripMain.Width - FToolStripMainControlsWidth;

         panelSearch.Refresh();
      }
      private void buttonSearch_Click(object sender, EventArgs e)
      {
         string query = "";

         if (textBoxName.Text != "") query += ServiceFields.FullName.ToString() + "=\"" + textBoxName.Text + "\" ";
         if (comboBoxLanguage.Text != "") query += ServiceFields.Language.ToString() + "=\"" + comboBoxLanguage.Text + "\" ";
         if (comboBoxCountry.Text != "") query += ServiceFields.Country.ToString() + "=\"" + comboBoxCountry.Text + "\" ";
         if (textBoxCity.Text != "") query += ServiceFields.City.ToString() + "=\"" + textBoxCity.Text + "\" ";
         if (comboBoxAge.Text != "") query += ServiceFields.Age.ToString() + "=\"" + comboBoxAge.Text + "\" ";
         if (comboBoxGender.SelectedIndex > 0) query += ServiceFields.Gender.ToString() + "=\"" + (comboBoxGender.Text == UserInfo.GetGenderAsString(1, true) ? 1 : 0) + "\" ";
         if (textBoxOrganization.Text != "") query += ServiceFields.Organization.ToString() + "=\"" + textBoxOrganization.Text + "\" ";
         if (textBoxDepartment.Text != "") query += ServiceFields.Department.ToString() + "=\"" + textBoxDepartment.Text + "\" ";
         if (checkBoxOnlineOnly.Checked) query += ServiceFields.NetworkStatus.ToString() + "=\"1\"";

         FCommunicator.SeekUsers(query, this);
      }
      private void buttonAddUser_Click(object sender, EventArgs e)
      {
         if (listViewResults.SelectedItems.Count == 0) return;

         User user = (User)listViewResults.SelectedItems[0].Tag;

         if (!FCommunicator.CurrentAccount.IsContact(user.Identifier))
         {
            FCommunicator.ShowAddContact(user, false);
         }
         else
         {
            FCommunicator.ShowError(Resources.S_User_is_already_in_your_contact_list.Replace("<user>", user.ToString()), null);
         }
      }
      private void buttonShowInfo_Click(object sender, EventArgs e)
      {
         if (listViewResults.SelectedItems.Count == 0) return;

         FCommunicator.ShowUserProperties((User)listViewResults.SelectedItems[0].Tag, "");
      }
      private void toolStrip_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.ToolStrip);
      }
      private void statusBar_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.StatusStrip);
         FCommunicator.DrawStatusBar(ColorTheme, sender as StatusStrip, e.Graphics);
      }
      private void panelHeader_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.Pattern);
      }
      private void panelSearch_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.Background);
      }
      private void buttonSendMessage_Click(object sender, EventArgs e)
      {
         if (listViewResults.SelectedItems.Count == 0) return;

         User user = (User)listViewResults.SelectedItems[0].Tag;
         Contact contact = FCommunicator.CurrentAccount.GetContact(user.Identifier);

         if (contact == null)
         {
            FCommunicator.AddContact(FCommunicator.CurrentAccount, user, null, true, "");
         }
         else
         {
            FCommunicator.OpenChatSession(contact, true);
         }         
      }
      private void buttonResetSearch_Click(object sender, EventArgs e)
      {
         ResetSearch();
      }
      private void buttonShowSearchPane_Click(object sender, EventArgs e)
      {
         SimpleMode = !SimpleMode;
      }
      private void labelSearchCloseButton_Click(object sender, EventArgs e)
      {
         buttonPeopleSearch.Checked = !buttonPeopleSearch.Checked;
      }
      private void window_OnWindowsThemeChanged(object sender, EventArgs e)
      {
         panelSearchParamsBodyBorder.BackColor = Color.White;

         panelSearchParamsHeaderBorder.BackColor = Color.White;

         switch (WindowsTheme)
         {
            case WindowsTheme.Blue:
            {
               tableLayoutPanelSearch.BackColor = FPanelSearchBlueColor;
               panelButtonSearch.BackColor = FSearchParamsBodyBlueColor;
               break;
            }
            case WindowsTheme.Olive:
            {
               tableLayoutPanelSearch.BackColor = FPanelSearchOliveColor;
               panelSearchParamsBody.BackColor = FSearchParamsBodyOliveColor;
               panelButtonSearch.BackColor = FSearchParamsBodyOliveColor;
               break;
            }
            case WindowsTheme.Silver:
            {
               tableLayoutPanelSearch.BackColor = FPanelSearchSilverColor;
               panelSearchParamsBody.BackColor = FSearchParamsBodySilverColor;
               panelButtonSearch.BackColor = FSearchParamsBodySilverColor;
               break;
            }
            default:
            {
               tableLayoutPanelSearch.BackColor = FPanelSearchStandardColor;
               panelSearchParamsBody.BackColor = SystemColors.ControlLight;
               panelButtonSearch.BackColor = SystemColors.ControlLight;
               panelSearchParamsBodyBorder.BackColor = Color.DarkGray;
               panelSearchParamsHeaderBorder.BackColor = Color.DarkGray;
               break;
            }
         }
      }
      private void listViewResults_KeyDown(object sender, KeyEventArgs e)
      {
         if (e.KeyCode == Keys.Apps && listViewResults.SelectedItems.Count == 1)
         {
            FCommunicator.Components.menuUser.Tag = listViewResults.SelectedItems[0].Tag;
            Point p = listViewResults.PointToScreen(listViewResults.GetItemRect(listViewResults.SelectedItems[0].Index).Location);
            MenuWrapper.ShowMenu(FCommunicator.Components.menuUser, p.X + 10, p.Y + 10);
         }
      }
      private void listViewResults_MouseUp(object sender, MouseEventArgs e)
      {
         if (listViewResults.SelectedItems.Count == 0) return;

         if (e.Button == MouseButtons.Right) FCommunicator.ShowUserMenu((User)listViewResults.SelectedItems[0].Tag);
      }
      private void panelCriteriaBody_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.Area);
      }
      private void panelCriteriaHeader_Paint(object sender, PaintEventArgs e)
      {
         FCommunicator.DrawTheme(ColorTheme, e.Graphics, (sender as Control).ClientRectangle, ColorThemeObject.PanelH);
      }
      private void textBoxQuickSearch_TextChanged(object sender, EventArgs e)
      {
         buttonGo.Enabled = textBoxQuickSearch.Text.Length > 0;
      }
      private void communicator_PropertyChanged(object sender, PropertyChangedEventArgs e)
      {
         if (e.PropertyName == "ColorTheme") ColorTheme = FCommunicator.ColorTheme;
         else if (e.PropertyName == "RenderMode") RenderMode = FCommunicator.RenderMode;
         else if (e.PropertyName == "Culture") Translate(FCommunicator.Culture);
      }
      private void communicator_SeekUsersState(object sender, NetworkOperationEventArgs e)
      {
         if (e.Error != null)
         {
            if (e.Error.ReasonCode != ErrorReasonCode.ExistAlready) ResetResultsView(SimpleMode);
            if (Visible) FCommunicator.ShowError("", e.Error);
         }
         else
         {
            if (e.State == OperationState.Callback || e.State == OperationState.Completed)
            {
               ShowResults(e.State, (IEnumerable<User>)e.Operation.Results["Users"]);
            }
            else if (e.State == OperationState.DataSending || e.State == OperationState.DataSent)
            {
               ResetResultsView(SimpleMode);
               statusBar.Items[0].Text = Resources.S_Looking_up_catalog;
            }
         }
      }
      private void communicator_CurrentAccountChanged(object sender, PropertyChangedEventArgs e)
      {
         labelCaption.Text = Resources.S_Search_people_at_service_catalog.Replace("<service>", FCommunicator.CurrentAccount.ServiceConfig.ToString());

         AssignCapabilities();
      }
   }
}
